package main.java.utils.hxy.thread.thread;

import com.google.common.collect.Maps;
import com.wanma.framework.util.IDate;

import java.util.Map;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 一些线程池的工具类
 *
 * @author kreo
 * @date 2020-3-19 12:57:06
 */
public class IPool {
    /**
     * 尝试关闭一个线程池 , 3秒后强制关闭(使用shutdownNow > interrupt , 不能保证能全部关掉)
     *
     * @param executor
     */
    public static void shutdown(ThreadPoolExecutor executor) {
        if (executor != null) {
            try {
                executor.shutdown();
                //等3秒钟 ,如果不结束则用shutdownNow
                if (!executor.awaitTermination(3l, TimeUnit.SECONDS)) {
                    executor.shutdownNow();
                }
            } catch (Exception e) {
                try {
                    // 异常后 , 尝试shutdownNow
                    executor.shutdownNow();
                } catch (Exception ex) {
                }
            }
        }
    }

    public static String getStatus(ThreadPoolExecutor executor) {
        if (executor == null) {
            return null;
        }
        StringBuffer sb = new StringBuffer();
        sb.append("[P:").append(executor.getPoolSize()).append("]")
                .append("[C:").append(executor.getCorePoolSize()).append("]")
                .append("[M:").append(executor.getMaximumPoolSize()).append("]")
                .append("[A:").append(executor.getActiveCount()).append("]");
        BlockingQueue<Runnable> queue = executor.getQueue();
        sb.append("[W:").append(queue.size()).append("]");
        if (queue instanceof TimeLinkedBlockingQueue) {
            sb.append("[T:").append(((TimeLinkedBlockingQueue) queue).getAvgWaitTime()).append("]");
        }
        return sb.toString();
    }

    /**
     * 重设线程池的大小
     *
     * @param executor
     * @param size
     */
    public static ThreadPoolExecutor setSize(ThreadPoolExecutor executor, int size) {
        executor.setCorePoolSize(size);
        executor.setMaximumPoolSize(size);
        return executor;
    }

    /**
     * 设置空闲时间超时时间
     *
     * @param executor
     * @param keepAliveSecond
     * @return
     */
    public static ThreadPoolExecutor setKeepAliveSecond(ThreadPoolExecutor executor, long keepAliveSecond) {
        executor.setKeepAliveTime(keepAliveSecond, TimeUnit.SECONDS);
        return executor;
    }

    static AtomicLong avg = new AtomicLong(0);

    private static InheritableThreadLocal<Map<String, Object>> runtime = new InheritableThreadLocal<>();

    public static void putRuntime(Map<String, Object> rtMap) {
        runtime.set(rtMap);
    }

    public static Map<String, Object> getRuntime() {
        return runtime.get();
    }

    public static void removeRuntime() {
        runtime.remove();
    }

    public static void putRuntimeEntry(String key, Object value) {
        Map<String, Object> rtMap = getRuntime();
        if (rtMap == null) {
            rtMap = Maps.newHashMap();
        }
        rtMap.put(key, value);
        putRuntime(rtMap);
    }

    public static <T> T getRuntimeKey(String key) {
        Map<String, Object> rtMap = getRuntime();
        if (rtMap == null) {
            return null;
        } else {
            return (T) rtMap.get(key);
        }
    }

    public static void removeRuntimeKey(String key) {
        Map<String, Object> rtMap = getRuntime();
        if (rtMap != null && rtMap.containsKey(key)) {
            rtMap.remove(key);
        }
        putRuntime(rtMap);
    }


    public static void main(String[] args) {
        Map<String, Object> m = Maps.newHashMap();
        m.put("AA", "AAA");
        m.put("BB", "BBB");
        IPool.putRuntime(m);
        try {
            for (int i = 0; i < 50; i++) {
                final int n = i;
                final long start = IDate.getNowMillis();
                IThreadPool.addTask(() -> {
                    try {
                        Random random = new Random();
                        int wait = random.nextInt(2000) + 1000;
                        System.out.println(">>>第" + n + "个线程启动 : " + wait + " >>>" + IPool.getRuntime());
                        Thread.sleep(wait);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        long exec = IDate.getNowMillis() - start;
                        avg.set((avg.get() + exec) / 2);
                        long execAvg = avg.get();
                        long waitAvg = IThreadPool.getQueue().getAvgWaitTime();
                        System.out.println("<<<第" + n + "个线程关闭 : " + exec + " (" + (execAvg - waitAvg) + ") 平均执行时间:" + execAvg + " 平均等待时间:" + waitAvg + " >>>" + IPool.getRuntime());
                    }

                    //64255
                });

                try {
                    Thread.sleep(200);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            System.out.println("=======================================>>>>>>>>>>>>>>>>>>>>>");


            // Thread.sleep(1000);
            // System.out.println("等1秒 , 查看线程池");
            // System.out.println(IPool.getStatus(executor));
            // executor.setCorePoolSize(3);
            // System.out.println("设置coreSize为3");
            // executor.getQueue().
            // 每1秒查看一次现场状态
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("我要REMOVEle");
            IPool.removeRuntime();
        }

    }
}
